﻿/*
 *********************************************************************
 *    Management Extensions for Windows Windows Server AppFabric     *
 *********************************************************************
 *    Author    : Fatih Boy [fatih@enterprisecoding.com]             *
 *    Web site  : http://www.enterprisecoding.com                    *
 *********************************************************************
 *    License   : GNU Library General Public License (LGPL)          * 
 *********************************************************************
 */

using System;
using System.ComponentModel;
using System.Windows.Forms;

using Microsoft.ApplicationServer.Caching;

using Microsoft.Web.Management.Client;
using Microsoft.Web.Management.Client.Win32;

using Com.Enterprisecoding.AppFabric.Extensions.Client.Resources.Cache;

namespace Com.Enterprisecoding.AppFabric.Extensions.Client.Pages.Cache.Accounts {
    [ModulePageIdentifier("17CD037C-C989-4E8B-A373-45604FD12830")]
    internal sealed class CacheAccountsPage : ModuleListPage {
        #region Data Members
        private CacheAccountServiceProxy cacheAccountServiceProxy;
        private ColumnHeader nameColumn;
        private ColumnHeader typeColumn;

        private ModuleListPageGrouping typeGrouping;

        private ListViewGroup userAccountsGroup;
        private ListViewGroup machineAccountsGroup;

        private CacheAccountsTaskList taskList;
        #endregion

        #region Properties
        public override ModuleListPageGrouping[] Groupings {
            get {
                if (typeGrouping == null) {
                    typeGrouping = new ModuleListPageGrouping("Type", Resources.Cache.CacheAccountsPage.AccountTypeGroupingText);

                    userAccountsGroup = new ListViewGroup(Resources.Cache.CacheAccountsPage.UserAccountsGroupTitle);
                    machineAccountsGroup = new ListViewGroup(Resources.Cache.CacheAccountsPage.MachineAccountsGroupTitle);
                }

                return new[] { typeGrouping };
            }
        }

        protected override bool CanRefresh {
            get { return true; }
        }

        internal bool HasAllowedAccount {
            get { return ListView.Items.Count > 0; }
        }

        internal bool HasSelectedAccount {
            get { return ListView.SelectedItems.Count > 0; }
        }

        internal CacheAcccountListViewItem SelectedItem {
            get {
                if (ListView.SelectedItems.Count > 0) {
                    return (CacheAcccountListViewItem)ListView.SelectedItems[0];
                }

                return null;
            }
        }

        protected override TaskListCollection Tasks {
            get {
                var tasks = base.Tasks;
                tasks.Add(taskList);

                return tasks;
            }
        }
        #endregion

        public CacheAccountsPage() {
            taskList = new CacheAccountsTaskList(this);
        }

        protected override void InitializeListPage() {
            nameColumn = new ColumnHeader {
                Text = Resources.Cache.CacheAccountsPage.NameColumnHeader,
                Width = 200
            };

            typeColumn = new ColumnHeader {
                Text = Resources.Cache.CacheAccountsPage.TypeColumnHeader,
                Width = 150
            };

            ListView.Columns.AddRange(new[] { nameColumn, typeColumn });
            ListView.MultiSelect = false;
            ListView.LabelWrap = false;
            ListView.SelectedIndexChanged += OnListViewSelectedIndexChanged;
        }

        protected override ListViewGroup[] GetGroups(ModuleListPageGrouping grouping) {
            if (grouping == typeGrouping) {
                return new[] { userAccountsGroup, machineAccountsGroup };
            }

            return null;
        }

        protected override void OnGroup(ModuleListPageGrouping grouping) {
            foreach (CacheAcccountListViewItem item in base.ListView.Items) {
                SetItemGroup(item);
            }
        }

        private void SetItemGroup(CacheAcccountListViewItem item) {
            if (base.SelectedGrouping == typeGrouping) {
                if (item.AccountType == AccountType.UserAccount) {
                    item.Group = userAccountsGroup;
                }
                else {
                    item.Group = machineAccountsGroup;
                }
            }
        }

        protected override bool ShowHelp() {
            //todo: implement show help
            return base.ShowHelp();
        }

        protected override bool ShowOnlineHelp() {
            //todo: implement show online help
            return base.ShowOnlineHelp();
        }

        protected override void OnActivated(bool initialActivation) {
            base.OnActivated(initialActivation);
            this.cacheAccountServiceProxy = (CacheAccountServiceProxy)base.CreateProxy(typeof(CacheAccountServiceProxy));

            if (initialActivation) {
                RetrieveAllowedAccounts();
            }
        }

        private void RetrieveAllowedAccounts() {
            base.StartAsyncTask(Resources.Cache.CacheAccountsPage.RetrieveAllowedAccountsProgressText, OnRetrieveAllowedAccounts, OnRetrieveAllowedAccountsCompleted);
        }

        private void OnRetrieveAllowedAccounts(object sender, DoWorkEventArgs e) {
            e.Result = cacheAccountServiceProxy.GetAllowedClientAccounts();
        }

        private void OnRetrieveAllowedAccountsCompleted(object sender, RunWorkerCompletedEventArgs e) {
            ListView.BeginUpdate();
            ListView.Items.Clear();

            //if (e.Error != null) {
            //    if (e.Error.InnerException != null && e.Error.InnerException is DataCacheException) {
            //        var innerEx = (DataCacheException)e.Error.InnerException;

            //        var managementUIService = (IManagementUIService)base.GetService(typeof(IManagementUIService));
            //        managementUIService.ShowError(innerEx, CacheAccounts.RetrieveAllowedAccountsExceptionMessage, CacheAccounts.RetrieveAllowedAccountsExceptionCaption, false);
            //        return;
            //    }
            //}

            try {
                var result = (CacheAccountEntry[])e.Result;

                foreach (var cacheAccount in result) {
                    ListView.Items.Add(new CacheAcccountListViewItem(cacheAccount.AccountName));
                }

                var selectedGrouping = base.SelectedGrouping;
                if (selectedGrouping != null) {
                    base.Group(selectedGrouping);
                }

                base.Update();
            }
            catch (Exception ex) {
                //base.DisplayErrorMessage(ex, Resources.ResourceManager);
            }
            finally {
                ListView.EndUpdate();
            }
        }

        private void OnListViewSelectedIndexChanged(object sender, EventArgs e) {
            base.Update();
        }

        protected override void Refresh() {
            RetrieveAllowedAccounts();
        }

        #region Task Item Functions
        internal void AddAccount() {
            var managementUIService = (IManagementUIService)base.GetService(typeof(IManagementUIService));

            try {
                var account2Add = new Account2Add((IServiceProvider)Module);

                if (ShowDialog(account2Add) == System.Windows.Forms.DialogResult.OK) {
                    cacheAccountServiceProxy.GrantCacheAllowedClientAccount(account2Add.AccountName, account2Add.Force);

                    var cacheAccountItem = new CacheAcccountListViewItem(account2Add.AccountName);
                    ListView.Items.Add(cacheAccountItem);

                    SetItemGroup(cacheAccountItem);

                    base.Update();
                    managementUIService.ShowMessage(Resources.Cache.CacheAccountsPage.AddAccountResultText, Resources.Cache.CacheAccountsPage.AddAccountResultCaption);
                }
            }
            catch (Exception ex) {
                if (ex.InnerException != null && ex.InnerException is DataCacheException) {
                    var innerEx = (DataCacheException)ex.InnerException;

                    switch (innerEx.ErrorCode) {
                        case DataCacheErrorCode.CacheAdminWindowsAccountInvalid:
                            managementUIService.ShowMessage(Resources.Cache.CacheAccountsPage.WindowsAccountInvalid, Resources.Cache.CacheAccountsPage.AddAccountExceptionCaption, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                            return;
                        case DataCacheErrorCode.CacheAdminWindowsAccountAlreadyPresent:
                            managementUIService.ShowMessage(Resources.Cache.CacheAccountsPage.WindowsAccountAlreadyPresent, Resources.Cache.CacheAccountsPage.AddAccountExceptionCaption, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                            return;
                    }
                }

                managementUIService.ShowError(ex, Resources.Cache.CacheAccountsPage.AddAccountExceptionMessage, Resources.Cache.CacheAccountsPage.AddAccountExceptionCaption, false);
            }
        }

        internal void RemoveAccount() {
            var managementUIService = (IManagementUIService)base.GetService(typeof(IManagementUIService));

            var confirmationResult = managementUIService.ShowMessage(Resources.Cache.CacheAccountsPage.RemoveAccountQuestionMessage,
                Resources.Cache.CacheAccountsPage.RemoveAccountQuestionCaption,
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question);

            if (confirmationResult == DialogResult.No) { return; }

            try {
                cacheAccountServiceProxy.RevokeCacheAllowedClientAccount(((CacheAcccountListViewItem)ListView.SelectedItems[0]).AccountName);

                ListView.Items.RemoveAt(ListView.SelectedIndices[0]);
            }
            catch (Exception ex) {
                managementUIService.ShowError(ex, Resources.Cache.CacheAccountsPage.RemoveAccountExceptionMessage, Resources.Cache.CacheAccountsPage.RemoveAccountExceptionCaption, false);
            }
        }
        #endregion
    }
}